﻿using Mohe.Scada.Entities.Models.LineSystem;
using NLog;
using SchedulerExtension.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SchedulerExtension
{
    public class DynamicScheduler
    {
        private static ILogger _logger = LogManager.GetCurrentClassLogger();
        private readonly Random _random = new Random();

        private List<Process> _processes;
        private List<Hoist> _hoists;
        private List<FlyingBar> _flyingBars;
        // 遗传算法参数
        private int _populationSize = 10;
        private double _crossoverRate = 0.8;
        private double _mutationRate = 0.1;
        private int _maxGenerations = 2;
        private int _cycleTime;
        // 实时数据
        private Queue<FlyingBar> _pendingOrders = new Queue<FlyingBar>();
        private object _lock = new object();


        public DynamicScheduler(List<Process> processes, List<Hoist> hoists, List<FlyingBar> initialBars, int cycleTime)
        {
            _processes = processes;
            _hoists = hoists;
            _flyingBars = initialBars;
            _cycleTime = cycleTime;
        }

        // 添加实时订单
        public void AddRealTimeOrder(FlyingBar newOrder)
        {
            lock (_lock)
            {
                _pendingOrders.Enqueue(newOrder);
            }
        }
        // 更新工艺信息
        public void UpdateProcessInfo(int processId,int processStep, int? newDuration, List<int> newAvailableTanks)
        {
            var process = _processes.FirstOrDefault(p => p.Id == processId);
            if (process != null)
            {
                //var step = process.Details.FirstOrDefault(x=>x.)
                //if (newDuration.HasValue)
                //    process. = newDuration.Value;

                //if (newAvailableTanks != null)
                //    process.AvailableTanks = newAvailableTanks;
            }
        }
        // 动态调度主循环
        public void RunSchedulingLoop()
        {
            while (true)
            {
                // 检查是否有新订单
                CheckNewOrders();

                // 执行遗传算法调度
                var bestSchedule = RunGeneticAlgorithm();

                // 应用最佳调度方案
                ApplySchedule(bestSchedule);

                // 模拟时间推进
                System.Threading.Thread.Sleep(5000); // 5秒调度一次
            }
        }

        private void CheckNewOrders()
        {
            lock (_lock)
            {
                while (_pendingOrders.Count > 0)
                {
                    var newOrder = _pendingOrders.Dequeue();
                    _flyingBars.Add(newOrder);
                    Console.WriteLine($"新订单加入: {newOrder.Name}");
                }
            }
        }

        private Chromosome RunGeneticAlgorithm()
        {
            var population = InitializePopulation();
            Chromosome bestChromosome = null;
            double bestFitness = double.MinValue;

            for (int gen = 0; gen < _maxGenerations; gen++)
            {
                // 评估适应度
                EvaluatePopulation(population);

                // 选择最佳个体
                var currentBest = population.OrderByDescending(c => c.Fitness).First();
                if (currentBest.Fitness > bestFitness)
                {
                    bestChromosome = currentBest.Clone();
                    bestFitness = currentBest.Fitness;
                    Console.WriteLine($"代数:{gen} bestFitness:{bestFitness}");
                }

                // 生成新一代
                var newPopulation = new List<Chromosome> { bestChromosome.Clone() };
                while (newPopulation.Count < _populationSize)
                {
                    var parent1 = Select(population);
                    var parent2 = Select(population);
                    var child = Crossover(parent1, parent2);
                    Mutate(child);
                    newPopulation.Add(child);
                }

                population = newPopulation;
            }

            return bestChromosome;
        }

        private List<Chromosome> InitializePopulation()
        {
            var population = new List<Chromosome>();

            for (int i = 0; i < _populationSize; i++)
            {
                var chromosome = new Chromosome
                {
                    //TankSelections = new int[_processes.Count],
                    FBarSelections = new int[_flyingBars.Count],
                    Schedule = new Dictionary<int, Dictionary<int, (double, double, int)>>()
                };

                //// 随机选择工艺路径
                for (int j = 0; j < _flyingBars.Count; j++)
                {
                    chromosome.FBarSelections[j] = _flyingBars[j].Id;
                }

                //// 随机选择槽位
                //for (int k = 0; k < _processes.Count; k++)
                //{
                //    var availableTanks = _processes[k].AvailableTanks;
                //    chromosome.TankSelections[k] = availableTanks[_random.Next(availableTanks.Count)];
                //}

                population.Add(chromosome);
            }

            return population;
        }

        private void EvaluatePopulation(List<Chromosome> population)
        {
            foreach (var chromosome in population)
            {
                // 计算调度
                CalculateSchedule(chromosome);

                // 计算适应度
                chromosome.Fitness = CalculateFitness(chromosome);
            }
        }

        private void CalculateSchedule(Chromosome chromosome)
        {
            List<TankLoad> tankLoads = _processes.SelectMany(t => t.AvailableTanks.Distinct())
                                        .Select(tankId => new TankLoad { TankId = tankId, TotalUsageTime = 0 }).ToList();
            chromosome.Schedule.Clear();
            var craneSchedules = _hoists.ToDictionary(c => c.Id, c => new List<(double start, double end)>());
            var processDict = _processes.ToDictionary(p => p.Id);
            double totalTime = 0;
            double totalTaktDeviation = 0;
            //double totalPriorityScore = 0;
            _flyingBars.ForEach(b => { b.EndTime = 0; });

            // 按优先级排序飞巴
            //var orderedBars = _flyingBars.OrderByDescending(b => b.Priority).ToList();

            for (int i = 0; i < _flyingBars.Count; i++)
            {
                var bar = _flyingBars.Where(t => t.Id == chromosome.FBarSelections[i]).First();
                var path = _processPaths[bar.SelectedPathIndex];
                chromosome.Schedule[bar.Id] = new Dictionary<int, (double, double, int)>();

                double barStartTime = 0;
                double barEndTime = 0;

                foreach (var processId in path.ProcessSequence)
                {
                    var process = processDict[processId];

                    var minLoadTank = tankLoads.Where(t => process.AvailableTanks.Contains(t.TankId)).OrderBy(t => t.TotalUsageTime).First();
                    int tank = minLoadTank.TankId;
                    var crane = _hoists.First(c => c.Id == process.CraneId);
                    var tasks = craneSchedules[crane.Id];

                    // 计算最早开始时间
                    double earliestStart = barStartTime;

                    // 检查前驱工序
                    if (process.PreviousProcessId.HasValue && chromosome.Schedule[bar.Id].ContainsKey(process.PreviousProcessId.Value))
                    {
                        earliestStart = chromosome.Schedule[bar.Id][process.PreviousProcessId.Value].end;
                    }
                    int travelTime = Math.Abs(crane.CurrentPosition - tank);
                    crane.CurrentPosition = tank;
                    // 查找可用时间槽
                    double startTime = FindAvailableSlot(tasks, earliestStart, travelTime + 40);
                    double endTime = startTime + travelTime + 40;

                    // 记录任务,行车的调用任务
                    tasks.Add((startTime, endTime));
                    startTime = endTime;
                    endTime = startTime + process.Duration;
                    //槽子的处理任务
                    chromosome.Schedule[bar.Id][process.Id] = (startTime, endTime, tank);
                    barEndTime = Math.Max(barEndTime, endTime);
                    minLoadTank.TotalUsageTime += process.Duration;
                    // 更新行车任务列表
                    craneSchedules[crane.Id] = tasks.OrderBy(t => t.start).ToList();
                }
                bar.EndTime = (int)barEndTime;
                totalTime = Math.Max(totalTime, barEndTime);
                //totalPriorityScore += bar.Priority * (1.0 / (1.0 + barEndTime));
            }
            var orderedBars = _flyingBars.OrderBy(b => b.EndTime).ToList();
            // 计算节拍偏差
            if (orderedBars.Count > 1)
            {
                for (int i = 1; i < _flyingBars.Count; i++)
                {
                    totalTaktDeviation += Math.Abs((_flyingBars[i].EndTime - _flyingBars[i - 1].EndTime) - _cycleTime); // 假设目标节拍15
                }
                totalTaktDeviation /= (_flyingBars.Count - 1);
            }

            chromosome.TotalTime = totalTime;
            chromosome.TaktTimeDeviation = totalTaktDeviation;
            //chromosome.PriorityScore = totalPriorityScore;
        }

        private double FindAvailableSlot(
            List<(double start, double end)> tasks,
            double earliestStart, double duration)
        {
            double startTime = earliestStart;
            bool conflict = false;
            do
            {
                foreach (var task in tasks)
                {
                    // 槽位冲突检查
                    if (task.end <= startTime || task.start >= startTime + duration)
                    {
                        conflict = true;
                        startTime = task.end;
                        break;
                    }

                }
                if (!conflict)
                    return startTime;

            } while (!conflict);
            return startTime;
        }

        private double CalculateFitness(Chromosome chromosome)
        {
            // 标准化各项指标
            double maxTime = chromosome.TotalTime;
            double maxTaktDev = chromosome.TaktTimeDeviation;
            //double maxPriority = chromosome.PriorityScore;

            // 加权适应度
            return (0.7 * (1.0 / (1.0 + maxTime)) +
                   (0.3 * (1.0 / (1.0 + maxTaktDev))));
        }

        private Chromosome Select(List<Chromosome> population)
        {
            double totalFitness = population.Sum(c => c.Fitness);
            double randomValue = _random.NextDouble() * totalFitness;
            double cumulative = 0;

            foreach (var c in population)
            {
                cumulative += c.Fitness;
                if (cumulative >= randomValue)
                    return c;
            }

            return population.Last();
        }

        private Chromosome Crossover(Chromosome p1, Chromosome p2)
        {
            var c1 = p1.Clone();
            if (_random.NextDouble() < _crossoverRate)
            {
                int start = new Random().Next(0, p1.FBarSelections.Length);
                int end = new Random().Next(start, p1.FBarSelections.Length);

                var childGene = new int[p1.FBarSelections.Length];
                for (int i = 0; i < p1.FBarSelections.Length; i++)
                {
                    if (i >= start && i <= end)
                    {
                        childGene[i] = p1.FBarSelections[i];
                    }
                }
                int index = 0;
                for (int i = 0; i < p2.FBarSelections.Length; i++)
                {
                    if (!childGene.Contains(p2.FBarSelections[i]))
                    {
                        while (childGene[index] != 0)
                        {
                            index++;
                        }
                        childGene[index] = p2.FBarSelections[i];
                    }
                }
                c1.FBarSelections = childGene;
                return c1;
            }
            return p1;
        }

        private void Mutate(Chromosome chromosome)
        {
            if (new Random().NextDouble() > _mutationRate)
            {
                return;
            }

            int index1 = new Random().Next(0, chromosome.FBarSelections.Length);
            int index2 = new Random().Next(0, chromosome.FBarSelections.Length);

            var temp = chromosome.FBarSelections[index1];
            chromosome.FBarSelections[index1] = chromosome.FBarSelections[index2];
            chromosome.FBarSelections[index2] = temp;
        }

        private void ApplySchedule(Chromosome bestChromosome)
        {
            Console.WriteLine("\n应用最佳调度方案:");
            Console.WriteLine($"总时间: {bestChromosome.TotalTime:F1}, 节拍偏差: {bestChromosome.TaktTimeDeviation:F1}");

            foreach (var bar in _flyingBars.OrderBy(b => b.EndTime))
            {
                var path = _processPaths[bar.SelectedPathIndex];
                Console.WriteLine($"\n飞巴 {bar.Name} , 路径: {path.Name}");

                foreach (var processId in path.ProcessSequence)
                {
                    var timing = bestChromosome.Schedule[bar.Id][processId];
                    Console.WriteLine($"  工序 {processId}: 槽位 {timing.tank}, 时间 {timing.start:F1}-{timing.end:F1}");
                }
            }
        }
    }
}
